home *** CD-ROM | disk | FTP | other *** search
/ Team Palmtops 7 / Palmtops_numero07.iso / WinCE / SDKWindowsCE / HandHeldPCPro30 / sdk.exe / Jupiter SDK / data1.cab / MFC / src / olefact.cpp < prev    next >
Encoding:
C/C++ Source or Header  |  1999-02-19  |  14.7 KB  |  597 lines

  1. // This is a part of the Microsoft Foundation Classes C++ library.
  2. // Copyright (C) 1992-1998 Microsoft Corporation
  3. // All rights reserved.
  4. //
  5. // This source code is only intended as a supplement to the
  6. // Microsoft Foundation Classes Reference and related
  7. // electronic documentation provided with the library.
  8. // See these sources for detailed information regarding the
  9. // Microsoft Foundation Classes product.
  10.  
  11. #include "stdafx.h"
  12.  
  13. #ifdef AFX_OLE3_SEG
  14. #pragma code_seg(AFX_OLE3_SEG)
  15. #endif
  16.  
  17. #ifdef _DEBUG
  18. #undef THIS_FILE
  19. static char THIS_FILE[] = __FILE__;
  20. #endif
  21.  
  22. #define new DEBUG_NEW
  23.  
  24. /////////////////////////////////////////////////////////////////////////////
  25. // COleObjectFactory implementation
  26.  
  27. BEGIN_INTERFACE_MAP(COleObjectFactory, CCmdTarget)
  28.     INTERFACE_PART(COleObjectFactory, IID_IClassFactory, ClassFactory)
  29.     INTERFACE_PART(COleObjectFactory, IID_IClassFactory2, ClassFactory)
  30. END_INTERFACE_MAP()
  31.  
  32. #ifdef AFX_INIT_SEG
  33. #pragma code_seg(AFX_INIT_SEG)
  34. #endif
  35.  
  36. COleObjectFactory::COleObjectFactory(REFCLSID clsid,
  37.     CRuntimeClass* pRuntimeClass, BOOL bMultiInstance, LPCTSTR lpszProgID)
  38. {
  39.     ASSERT(pRuntimeClass == NULL ||
  40.         pRuntimeClass->IsDerivedFrom(RUNTIME_CLASS(CCmdTarget)));
  41.     ASSERT(AfxIsValidAddress(&clsid, sizeof(CLSID), FALSE));
  42.     ASSERT(lpszProgID == NULL || AfxIsValidString(lpszProgID));
  43.  
  44.     // initialize to unregistered state
  45.     m_dwRegister = 0;   // not registered yet
  46.     m_bRegistered = FALSE;
  47.     m_clsid = clsid;
  48.     m_pRuntimeClass = pRuntimeClass;
  49.     m_bMultiInstance = bMultiInstance;
  50.     m_lpszProgID = lpszProgID;
  51.     m_bOAT = (BYTE) OAT_UNKNOWN;
  52.  
  53.     // licensing information
  54.     m_bLicenseChecked = FALSE;
  55.     m_bLicenseValid = FALSE;
  56.  
  57.     // add this factory to the list of factories
  58.     m_pNextFactory = NULL;
  59.     AFX_MODULE_STATE* pModuleState = _AFX_CMDTARGET_GETSTATE();
  60.     AfxLockGlobals(CRIT_OBJECTFACTORYLIST);
  61.     pModuleState->m_factoryList.AddHead(this);
  62.     AfxUnlockGlobals(CRIT_OBJECTFACTORYLIST);
  63.  
  64.     ASSERT_VALID(this);
  65. }
  66.  
  67. #ifdef AFX_TERM_SEG
  68. #pragma code_seg(AFX_TERM_SEG)
  69. #endif
  70.  
  71. COleObjectFactory::~COleObjectFactory()
  72. {
  73.     ASSERT_VALID(this);
  74.  
  75. #ifdef _AFXDLL
  76.     if (m_pModuleState == NULL)
  77.         return;
  78. #endif
  79.  
  80.     // deregister this class factory
  81. #if !defined(_WIN32_WCE) 
  82.     Revoke();
  83. #endif // _WIN32_WCE
  84.  
  85.     // remove this class factory from the list of active class factories
  86. #ifdef _AFXDLL
  87.     AFX_MODULE_STATE* pModuleState = m_pModuleState;
  88. #else
  89.     AFX_MODULE_STATE* pModuleState = _AFX_CMDTARGET_GETSTATE();
  90. #endif
  91.     AfxLockGlobals(CRIT_OBJECTFACTORYLIST);
  92.     BOOL bResult = pModuleState->m_factoryList.Remove(this);
  93.     AfxUnlockGlobals(CRIT_OBJECTFACTORYLIST);
  94.     if (bResult)
  95.         return;
  96.  
  97.     // check CDynLinkLibrary objects in case it was transfered during init
  98. #ifdef _AFXDLL
  99.     AfxLockGlobals(CRIT_DYNLINKLIST);
  100.     for (CDynLinkLibrary* pDLL = pModuleState->m_libraryList; pDLL != NULL;
  101.         pDLL = pDLL->m_pNextDLL)
  102.     {
  103.         if (pDLL->m_factoryList.Remove(this))
  104.         {
  105.             AfxUnlockGlobals(CRIT_DYNLINKLIST);
  106.             return;
  107.         }
  108.     }
  109.     AfxUnlockGlobals(CRIT_DYNLINKLIST);
  110. #endif
  111. }
  112.  
  113. #ifdef AFX_INIT_SEG
  114. #pragma code_seg(AFX_INIT_SEG)
  115. #endif
  116.  
  117. BOOL COleObjectFactory::Unregister()
  118. {
  119.     return TRUE;
  120. }
  121.  
  122. BOOL COleObjectFactory::Register()
  123. {
  124.     ASSERT_VALID(this);
  125.     ASSERT(!m_bRegistered);  // registering server/factory twice?
  126.     ASSERT(m_clsid != CLSID_NULL);
  127.  
  128.     if (!afxContextIsDLL)
  129.     {
  130.         // In the application variants, the IClassFactory is registered
  131.         //  with the OLE DLLs.
  132.  
  133. #if defined(_WIN32_WCE)
  134. // WinCE: CoRegisterClassObject is not supported
  135.         ASSERT(FALSE);
  136.         SCODE sc = S_FALSE;
  137. #else // _WIN32_WCE
  138.         SCODE sc = ::CoRegisterClassObject(m_clsid, &m_xClassFactory,
  139.             CLSCTX_LOCAL_SERVER,
  140.             m_bMultiInstance ? REGCLS_SINGLEUSE : REGCLS_MULTIPLEUSE,
  141.             &m_dwRegister);
  142. #endif // _WIN32_WCE
  143.         if (sc != S_OK)
  144.         {
  145. #ifdef _DEBUG
  146.             TRACE1("Warning: CoRegisterClassObject failed scode = %s.\n",
  147.                 ::AfxGetFullScodeString(sc));
  148. #endif
  149.             // registration failed.
  150.             return FALSE;
  151.         }
  152.         ASSERT(m_dwRegister != 0);
  153.     }
  154.  
  155.     ++m_bRegistered;
  156.     return TRUE;
  157. }
  158.  
  159. BOOL PASCAL COleObjectFactory::UnregisterAll()
  160. {
  161.     BOOL bResult = TRUE;
  162.     // register application factories
  163.     AFX_MODULE_STATE* pModuleState = AfxGetModuleState();
  164.     AfxLockGlobals(CRIT_OBJECTFACTORYLIST);
  165.     for (COleObjectFactory* pFactory = pModuleState->m_factoryList;
  166.         pFactory != NULL; pFactory = pFactory->m_pNextFactory)
  167.     {
  168.         // unregister any registered, non-doctemplate factories
  169.         if (pFactory->IsRegistered() && !pFactory->Unregister())
  170.         {
  171.             bResult = FALSE;
  172.         }
  173.     }
  174.     AfxUnlockGlobals(CRIT_OBJECTFACTORYLIST);
  175.     return bResult;
  176. }
  177.  
  178. BOOL PASCAL COleObjectFactory::RegisterAll()
  179. {
  180.     BOOL bResult = TRUE;
  181.     // register application factories
  182.     AFX_MODULE_STATE* pModuleState = AfxGetModuleState();
  183.     AfxLockGlobals(CRIT_OBJECTFACTORYLIST);
  184.     for (COleObjectFactory* pFactory = pModuleState->m_factoryList;
  185.         pFactory != NULL; pFactory = pFactory->m_pNextFactory)
  186.     {
  187.         // register any non-registered, non-doctemplate factories
  188.         if (!pFactory->IsRegistered() &&
  189.             pFactory->m_clsid != CLSID_NULL && !pFactory->Register())
  190.         {
  191.             bResult = FALSE;
  192.         }
  193.     }
  194.     AfxUnlockGlobals(CRIT_OBJECTFACTORYLIST);
  195. #ifdef _AFXDLL
  196.     // register extension DLL factories
  197.     AfxLockGlobals(CRIT_DYNLINKLIST);
  198.     for (CDynLinkLibrary* pDLL = pModuleState->m_libraryList; pDLL != NULL;
  199.         pDLL = pDLL->m_pNextDLL)
  200.     {
  201.         for (pFactory = pDLL->m_factoryList;
  202.             pFactory != NULL; pFactory = pFactory->m_pNextFactory)
  203.         {
  204.             // register any non-registered, non-doctemplate factories
  205.             if (!pFactory->IsRegistered() &&
  206.                 pFactory->m_clsid != CLSID_NULL && !pFactory->Register())
  207.             {
  208.                 bResult = FALSE;
  209.             }
  210.         }
  211.     }
  212.     AfxUnlockGlobals(CRIT_DYNLINKLIST);
  213. #endif
  214.     return bResult;
  215. }
  216.  
  217. #ifdef AFX_TERM_SEG
  218. #pragma code_seg(AFX_TERM_SEG)
  219. #endif
  220.  
  221. #if !defined(_WIN32_WCE)
  222. void COleObjectFactory::Revoke()
  223. {
  224.     ASSERT_VALID(this);
  225.  
  226.     if (m_bRegistered)
  227.     {
  228.         // revoke the registration of the class itself
  229.         if (m_dwRegister != 0)
  230.         {
  231.             ::CoRevokeClassObject(m_dwRegister);
  232.             m_dwRegister = 0;
  233.         }
  234.         m_bRegistered = FALSE;
  235.     }
  236. }
  237.  
  238. void PASCAL COleObjectFactory::RevokeAll()
  239. {
  240.     AFX_MODULE_STATE* pModuleState = AfxGetModuleState();
  241.     AfxLockGlobals(CRIT_OBJECTFACTORYLIST);
  242.     for (COleObjectFactory* pFactory = pModuleState->m_factoryList;
  243.         pFactory != NULL; pFactory = pFactory->m_pNextFactory)
  244.     {
  245.         pFactory->Revoke();
  246.     }
  247.     AfxUnlockGlobals(CRIT_OBJECTFACTORYLIST);
  248. #ifdef _AFXDLL
  249.     AfxLockGlobals(CRIT_DYNLINKLIST);
  250.     // register extension DLL factories
  251.     for (CDynLinkLibrary* pDLL = pModuleState->m_libraryList; pDLL != NULL;
  252.         pDLL = pDLL->m_pNextDLL)
  253.     {
  254.         for (pFactory = pDLL->m_factoryList;
  255.             pFactory != NULL; pFactory = pFactory->m_pNextFactory)
  256.         {
  257.             pFactory->Revoke();
  258.         }
  259.     }
  260.     AfxUnlockGlobals(CRIT_DYNLINKLIST);
  261. #endif
  262. }
  263. #endif // _WIN32_WCE
  264.  
  265. #ifdef AFX_OLE3_SEG
  266. #pragma code_seg(AFX_OLE3_SEG)
  267. #endif
  268.  
  269. void COleObjectFactory::UpdateRegistry(LPCTSTR lpszProgID)
  270. {
  271.     ASSERT_VALID(this);
  272.     ASSERT(lpszProgID == NULL || AfxIsValidString(lpszProgID));
  273.  
  274.     // use default prog-id if specific prog-id not given
  275.     if (lpszProgID == NULL)
  276.     {
  277.         lpszProgID = m_lpszProgID;
  278.         if (lpszProgID == NULL) // still no valid progID?
  279.             return;
  280.     }
  281.  
  282.     // call global helper to modify system registry
  283.     //  (progid, shortname, and long name are all equal in this case)
  284.     AfxOleRegisterServerClass(m_clsid, lpszProgID, lpszProgID, lpszProgID,
  285.         OAT_DISPATCH_OBJECT);
  286. }
  287.  
  288. BOOL PASCAL COleObjectFactory::UpdateRegistryAll(BOOL bRegister)
  289. {
  290.     AFX_MODULE_STATE* pModuleState = AfxGetModuleState();
  291.     AfxLockGlobals(CRIT_OBJECTFACTORYLIST);
  292.     for (COleObjectFactory* pFactory = pModuleState->m_factoryList;
  293.         pFactory != NULL; pFactory = pFactory->m_pNextFactory)
  294.     {
  295.         if (!pFactory->UpdateRegistry(bRegister))
  296.         {
  297.             AfxUnlockGlobals(CRIT_OBJECTFACTORYLIST);
  298.             return FALSE;
  299.         }
  300.     }
  301.     AfxUnlockGlobals(CRIT_OBJECTFACTORYLIST);
  302. #ifdef _AFXDLL
  303.     AfxLockGlobals(CRIT_DYNLINKLIST);
  304.     // register extension DLL factories
  305.     for (CDynLinkLibrary* pDLL = pModuleState->m_libraryList; pDLL != NULL;
  306.         pDLL = pDLL->m_pNextDLL)
  307.     {
  308.         for (pFactory = pDLL->m_factoryList;
  309.             pFactory != NULL; pFactory = pFactory->m_pNextFactory)
  310.         {
  311.             if (!pFactory->UpdateRegistry(bRegister))
  312.             {
  313.                 AfxUnlockGlobals(CRIT_DYNLINKLIST);
  314.                 return FALSE;
  315.             }
  316.         }
  317.     }
  318.     AfxUnlockGlobals(CRIT_DYNLINKLIST);
  319. #endif
  320.  
  321.     return TRUE;
  322. }
  323.  
  324. CCmdTarget* COleObjectFactory::OnCreateObject()
  325. {
  326.     ASSERT_VALID(this);
  327.     ASSERT(AfxIsValidAddress(m_pRuntimeClass, sizeof(CRuntimeClass), FALSE));
  328.         // this implementation needs a runtime class
  329.  
  330.     // allocate object, throw exception on failure
  331.     CCmdTarget* pTarget = (CCmdTarget*)m_pRuntimeClass->CreateObject();
  332.     if (pTarget == NULL)
  333.         AfxThrowMemoryException();
  334.  
  335.     // make sure it is a CCmdTarget
  336.     ASSERT_KINDOF(CCmdTarget, pTarget);
  337.     ASSERT_VALID(pTarget);
  338.  
  339.     // return the new CCmdTarget object
  340.     return pTarget;
  341. }
  342.  
  343. BOOL COleObjectFactory::IsLicenseValid()
  344. {
  345.     if (!m_bLicenseChecked)
  346.     {
  347.         m_bLicenseValid = (BYTE)VerifyUserLicense();
  348.         m_bLicenseChecked = TRUE;
  349.     }
  350.     return m_bLicenseValid;
  351. }
  352.  
  353. BOOL COleObjectFactory::UpdateRegistry(BOOL bRegister)
  354. {
  355.     if (bRegister)
  356.         UpdateRegistry();   // will register with default m_lpszProgID
  357.  
  358.     return TRUE;
  359. }
  360.  
  361. BOOL COleObjectFactory::VerifyUserLicense()
  362. {
  363.     // May be overridden by subclass
  364.     return TRUE;
  365. }
  366.  
  367. BOOL COleObjectFactory::GetLicenseKey(DWORD, BSTR*)
  368. {
  369.     // May be overridden by subclass
  370.     return FALSE;
  371. }
  372.  
  373. BOOL COleObjectFactory::VerifyLicenseKey(BSTR bstrKey)
  374. {
  375.     // May be overridden by subclass
  376.  
  377.     BOOL bLicensed = FALSE;
  378.     BSTR bstr = NULL;
  379.  
  380.     if ((bstrKey != NULL) && GetLicenseKey(0, &bstr))
  381.     {
  382.         ASSERT(bstr != NULL);
  383.  
  384.         // if length and content match, it's good!
  385.  
  386.         UINT cch = SysStringByteLen(bstr);
  387.         if ((cch == SysStringByteLen(bstrKey)) &&
  388.             (memcmp(bstr, bstrKey, cch) == 0))
  389.         {
  390.             bLicensed = TRUE;
  391.         }
  392.  
  393.         SysFreeString(bstr);
  394.     }
  395.  
  396.     return bLicensed;
  397. }
  398.  
  399. /////////////////////////////////////////////////////////////////////////////
  400. // Implementation of COleObjectFactory::IClassFactory interface
  401.  
  402. STDMETHODIMP_(ULONG) COleObjectFactory::XClassFactory::AddRef()
  403. {
  404.     METHOD_PROLOGUE_EX_(COleObjectFactory, ClassFactory)
  405.     return pThis->InternalAddRef();
  406. }
  407.  
  408. STDMETHODIMP_(ULONG) COleObjectFactory::XClassFactory::Release()
  409. {
  410.     METHOD_PROLOGUE_EX_(COleObjectFactory, ClassFactory)
  411.     return pThis->InternalRelease();
  412. }
  413.  
  414. STDMETHODIMP COleObjectFactory::XClassFactory::QueryInterface(
  415.     REFIID iid, LPVOID* ppvObj)
  416. {
  417.     METHOD_PROLOGUE_EX_(COleObjectFactory, ClassFactory)
  418.     return pThis->InternalQueryInterface(&iid, ppvObj);
  419. }
  420.  
  421. STDMETHODIMP COleObjectFactory::XClassFactory::CreateInstance(
  422.     IUnknown* pUnkOuter, REFIID riid, LPVOID* ppvObject)
  423. {
  424.     return CreateInstanceLic(pUnkOuter, NULL, riid, NULL, ppvObject);
  425. }
  426.  
  427. STDMETHODIMP COleObjectFactory::XClassFactory::LockServer(BOOL fLock)
  428. {
  429.     METHOD_PROLOGUE_EX(COleObjectFactory, ClassFactory)
  430.     ASSERT_VALID(pThis);
  431.  
  432.     SCODE sc = E_UNEXPECTED;
  433.     TRY
  434.     {
  435.         if (fLock)
  436.             AfxOleLockApp();
  437.         else
  438.             AfxOleUnlockApp();
  439.         sc = S_OK;
  440.     }
  441.     END_TRY
  442.  
  443.     return sc;
  444. }
  445.  
  446. STDMETHODIMP COleObjectFactory::XClassFactory::GetLicInfo(
  447.     LPLICINFO pLicInfo)
  448. {
  449.     METHOD_PROLOGUE_EX(COleObjectFactory, ClassFactory)
  450.     ASSERT_VALID(pThis);
  451.  
  452.     BSTR bstr = NULL;
  453.     pLicInfo->fLicVerified = pThis->IsLicenseValid();
  454.     pLicInfo->fRuntimeKeyAvail = pThis->GetLicenseKey(0, &bstr);
  455.     if (bstr != NULL)
  456.         SysFreeString(bstr);
  457.  
  458.     return S_OK;
  459. }
  460.  
  461. STDMETHODIMP COleObjectFactory::XClassFactory::RequestLicKey(
  462.     DWORD dwReserved, BSTR* pbstrKey)
  463. {
  464.     METHOD_PROLOGUE_EX(COleObjectFactory, ClassFactory)
  465.     ASSERT_VALID(pThis);
  466.  
  467.     ASSERT(pbstrKey != NULL);
  468.  
  469.     *pbstrKey = NULL;
  470.  
  471.     if (pThis->IsLicenseValid())
  472.     {
  473.         if (pThis->GetLicenseKey(dwReserved, pbstrKey))
  474.             return S_OK;
  475.         else
  476.             return E_FAIL;
  477.     }
  478.     else
  479.         return CLASS_E_NOTLICENSED;
  480. }
  481.  
  482. STDMETHODIMP COleObjectFactory::XClassFactory::CreateInstanceLic(
  483.     LPUNKNOWN pUnkOuter, LPUNKNOWN /* pUnkReserved */, REFIID riid,
  484.     BSTR bstrKey, LPVOID* ppvObject)
  485. {
  486.     METHOD_PROLOGUE_EX(COleObjectFactory, ClassFactory)
  487.     ASSERT_VALID(pThis);
  488.  
  489.     *ppvObject = NULL;
  490.  
  491.     if (((bstrKey != NULL) && !pThis->VerifyLicenseKey(bstrKey)) ||
  492.         ((bstrKey == NULL) && !pThis->IsLicenseValid()))
  493.         return CLASS_E_NOTLICENSED;
  494.  
  495.     // outer objects must ask for IUnknown only
  496.     ASSERT(pUnkOuter == NULL || riid == IID_IUnknown);
  497.  
  498.     // attempt to create the object
  499.     CCmdTarget* pTarget = NULL;
  500.     SCODE sc = E_OUTOFMEMORY;
  501.     TRY
  502.     {
  503.         // attempt to create the object
  504.         pTarget = pThis->OnCreateObject();
  505.         if (pTarget != NULL)
  506.         {
  507.             // check for aggregation on object not supporting it
  508.             sc = CLASS_E_NOAGGREGATION;
  509.             if (pUnkOuter == NULL || pTarget->m_xInnerUnknown != 0)
  510.             {
  511.                 // create aggregates used by the object
  512.                 pTarget->m_pOuterUnknown = pUnkOuter;
  513.                 sc = E_OUTOFMEMORY;
  514.                 if (pTarget->OnCreateAggregates())
  515.                     sc = S_OK;
  516.             }
  517.         }
  518.     }
  519.     END_TRY
  520.  
  521.     // finish creation
  522.     if (sc == S_OK)
  523.     {
  524.         DWORD dwRef = 1;
  525.         if (pUnkOuter != NULL)
  526.         {
  527.             // return inner unknown instead of IUnknown
  528.             *ppvObject = &pTarget->m_xInnerUnknown;
  529.         }
  530.         else
  531.         {
  532.             // query for requested interface
  533.             sc = pTarget->InternalQueryInterface(&riid, ppvObject);
  534.             if (sc == S_OK)
  535.             {
  536.                 dwRef = pTarget->InternalRelease();
  537.                 ASSERT(dwRef != 0);
  538.             }
  539.         }
  540.         if (dwRef != 1)
  541.             TRACE1("Warning: object created with reference of %ld\n", dwRef);
  542.     }
  543.  
  544.     // cleanup in case of errors
  545.     if (sc != S_OK)
  546.         delete pTarget;
  547.  
  548.     return sc;
  549. }
  550.  
  551. //////////////////////////////////////////////////////////////////////////////
  552. // Diagnostics
  553.  
  554. #ifdef _DEBUG
  555. void COleObjectFactory::AssertValid() const
  556. {
  557.     CCmdTarget::AssertValid();
  558.     ASSERT(m_lpszProgID == NULL || AfxIsValidString(m_lpszProgID));
  559.     ASSERT(m_pRuntimeClass == NULL ||
  560.         AfxIsValidAddress(m_pRuntimeClass, sizeof(CRuntimeClass), FALSE));
  561.     ASSERT(m_pNextFactory == NULL ||
  562.         AfxIsValidAddress(m_pNextFactory, sizeof(COleObjectFactory)));
  563. }
  564.  
  565. void COleObjectFactory::Dump(CDumpContext& dc) const
  566. {
  567.     USES_CONVERSION;
  568.  
  569.     CCmdTarget::Dump(dc);
  570.  
  571.     dc << "m_pNextFactory = " << (void*)m_pNextFactory;
  572.     dc << "\nm_dwRegister = " << m_dwRegister;
  573.     dc << "\nm_bRegistered = " << m_bRegistered;
  574.     LPOLESTR lpszClassID = NULL;
  575.     if (StringFromCLSID(m_clsid, &lpszClassID) == S_OK)
  576.     {
  577.         dc << "\nm_clsid = " << OLE2CT(lpszClassID);
  578.         CoTaskMemFree(lpszClassID);
  579.     }
  580.     dc << "\nm_pRuntimeClass = " << m_pRuntimeClass;
  581.     dc << "\nm_bMultiInstance = " << m_bMultiInstance;
  582.     dc << "\nm_lpszProgID = " << m_lpszProgID;
  583.     dc << "\nm_bLicenseChecked = " << m_bLicenseChecked;
  584.     dc << "\nm_bLicenseValid = " << m_bLicenseValid;
  585.  
  586.     dc << "\n";
  587. }
  588. #endif //_DEBUG
  589.  
  590. #ifdef AFX_INIT_SEG
  591. #pragma code_seg(AFX_INIT_SEG)
  592. #endif
  593.  
  594. IMPLEMENT_DYNAMIC(COleObjectFactory, CCmdTarget)
  595.  
  596. /////////////////////////////////////////////////////////////////////////////
  597.